package gengine.serverside;

import gengine.common.misc.BaseApplication;
import gengine.common.misc.LogCategory;
import gengine.common.packets.BasePacket;
import gengine.common.packets.client.ClientInfoPacket;
import gengine.common.packets.server.InitPacket;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

/**
 * User: arseniy
 * Date: 20.12.11
 */
public class ServerThread extends Thread {

    ServerSocket socket;
    List<ServerClient> clients = new ArrayList<ServerClient>();
    int lastClientId = 1;
    int port;
    private BaseApplication app;


    public ServerThread(BaseApplication application, int port) {
        this.app = application;
        this.port = port;
    }


    @Override
    public void run() {
        try {
            socket = new ServerSocket(port);
            ServerApplication.log("Starting listening at port " + Integer.toString(port), LogCategory.Info);
        } catch (IOException e) {
            ServerApplication.log("Error binding to port" + Integer.toString(port), LogCategory.Error);
            e.printStackTrace();
            app.quit();
            return;
        }
        try {
            while (true) {
                Socket cl = socket.accept();
                ServerApplication.log("ClientThread connected", LogCategory.Info);
                ServerClient c = new ServerClient(cl, this, lastClientId++);
                clients.add(c);
                c.start();
                c.sendPacketImmediately(new InitPacket("Hello", c.getClientId()));
                BroadcastPacket(new ClientInfoPacket(c.getClientId(),c.clientInfo));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void interrupt() {
        for (ServerClient cl : clients)
            cl.interrupt();
        super.interrupt();
    }

    public void BroadcastPacket(BasePacket packet) {
        removeDeadClients();
        for (ServerClient client : clients) {
            client.sendPacketImmediately(packet);
        }
    }

    private void removeDeadClients() {
        synchronized (clients) {
            for (int i = clients.size() - 1; i >= 0; i--)
                if (!clients.get(i).isConnected()) {
                    System.out.printf("ClientThread %d disconnected\n", clients.get(i).getClientId());
                    clients.remove(i);
                }
        }
    }

    public ServerClient getClientById(int clientId) {
        removeDeadClients();
        for (ServerClient client : clients) {
            if (client.getClientId() == clientId)
                return client;
        }
        return null;

    }
}
